package gods.bubble.preprocess;

import gods.bubble.util.Config;
import gods.bubble.util.SimpleFileIOUtil;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

public class PageRank {
	HashMap<String, Page> pages = new HashMap<String, Page>();
	
	public void loadFromFile(File linkFile) throws IOException {
		BufferedReader reader = null;
		
        reader = new BufferedReader(new FileReader(linkFile));
        String line = null;
        
        while ((line = reader.readLine()) != null && line.length() > 0) {
           String[] ids = line.split("\t");
           
           Page current_page = pages.get(ids[0]);
           
           if (!pages.keySet().contains(ids[1])) {
        	   current_page = new Page();
        	   current_page.title = ids[0];
        	   current_page.url = ids[1];
        	   
        	   pages.put(ids[1], current_page);
           }
           else {
        	   current_page = pages.get(ids[1]);
           }
           
           for (int i = 2; i < ids.length; i++) {
        	   Page page = null;
        	   
        	   if (!pages.keySet().contains(ids[i])) {
            	   page = new Page();
            	   page.url = ids[i];
            	   
            	   pages.put(ids[i], page);
               }
        	   else {
        		   page = pages.get(ids[i]);
        	   }
        	   
        	   current_page.outPages.add(page);
        	   
        	   page.inlink ++;
        	   current_page.outlink ++;
           }
        }
        
        for (Page page : pages.values()) {
        	if (page.title == null) {
        		page.title = "No Title Document";
        	}
        }
        
        reader.close();
        
        System.out.println("Load from file succeed! Got " + pages.size() + " pages");
	}
	
	public void makePR(File pagerankFile) throws IOException {
		long start = System.currentTimeMillis();

		int N = pages.size();

		// Set initial value
		for (Page p : pages.values()) {
			p.pagerank = 1.0 / N;
		}

		int k = 10000;
		double alpha = 0.2;

		for (int i = 0; i < k; i++) {
			for (Page p : pages.values()) {
				p.pagerank_last = p.pagerank;
				p.pagerank = alpha / N;
			}

			double from_zero_outlink_page = 0;

			for (Page p : pages.values()) {
				if (p.outlink != 0) {
					for (Page son : p.outPages) {
						son.pagerank += (1 - alpha)
								* p.pagerank_last / p.outlink;
					}
				} else {
					from_zero_outlink_page += (1 - alpha)
							* p.pagerank_last / N;
				}
			}

			for (Page p : pages.values()) {
				p.pagerank += from_zero_outlink_page;
			}
		}

		long finish = System.currentTimeMillis();

		System.out.println("Page Rank(Standard) take " + (finish - start)
				+ " milliseconds");

		// Output Result
		StringBuilder result = new StringBuilder();
		ArrayList<Double> pageranks = new ArrayList<Double>();

		double total = 0;

		for (Page p : pages.values()) {
			result.append(p.title + '\t' + p.url + '\t' + p.pagerank + '\n');

			pageranks.add(p.pagerank);
			total += p.pagerank;
		}

		System.out.println("PageRank(Standard) got a sum of " + total);

		SimpleFileIOUtil.stringToFile(result.toString(), pagerankFile, "utf8");
	}
	
	public static void main(String args[]) throws IOException {
		File linkFile = new File(Config.linkFile);
		File pagerankFile = new File(Config.pagerankFile);
		
		PageRank pr = new PageRank();
		
		pr.loadFromFile(linkFile);
		pr.makePR(pagerankFile);
	}
}

class Page {
	String title;
	String url;
	
	int inlink = 0;
	int outlink = 0;
	
	double pagerank_last;
	double pagerank;
	
	ArrayList<Page> outPages = new ArrayList<Page>();
}
